/*
 * N_Level_Network.java
 *
 * 
 */

package it.luigiarpino.alt2jsim.network;

import java.util.StringTokenizer;
import java.util.Vector;
/**
 *
 * @author  Luigi Lorenzo Arpino 534/559
 */
public class N_Level_Network extends Net {
    
    /** Creates a new instance of N_Level_Network */
    public N_Level_Network(int numOfNode_,int numOfArch_,int scale_, String[] nomiNodi_,int [][] archi_,int[][] posizioneNodi_) {
        super(numOfNode_, numOfArch_, scale_,  nomiNodi_, archi_,posizioneNodi_); 
    }
    
    public int getNumOfLevel(){
        String stringa=this.nomiNodi[0];
        byte[] st=stringa.getBytes();
        byte[] x=".".getBytes();
        int num=0;
        for (int i=0;i<stringa.length();i++){
            if (st[i]==x[0]){
                num++;
            }
        }
        num++;
        return num; 
    }
    
    /** Restituisce il numero di reti appartenenti al primo livello */
    public int getNumOfFirstLevelNetwork(){
        Integer max=new Integer(-1);
        for(int i=0;i<this.numOfNode;i++){
            StringTokenizer st=new StringTokenizer(this.nomiNodi[i]);
            Integer network=new Integer(st.nextToken("."));
            if (network.intValue()>max.intValue()){
                max=new Integer(network.intValue());
            }
        }
        return max.intValue()+1;
    }
    
    /** Restituisce il numero di reti appartenenti al secondo livello*/
    public int getNumOfSecondLevelNetwork(){
        if(this.getNumOfLevel()>1){
            return this.getLevel_2_Name().length;
        }
        else{
            return 0;
        }
    }
    
    /** Restituisce il numero di reti appartenenti al terzo livello*/
    public int getNumOfThirdLevelNetwork(){
        if(this.getNumOfLevel()>2){
            return this.getLevel_3_Name().length;
        }
        else{
            return 0;
        }
    }
    
    private int getFirstLevelNetworkOfNode(int nodo_id_){
        StringTokenizer st=new StringTokenizer(this.nomiNodi[nodo_id_]);
        Integer num=new Integer(st.nextToken("."));
        return num.intValue();
    }
    
    private int getSecondLevelNetworkOfNode(int nodo_id_){
        StringTokenizer st=new StringTokenizer(this.nomiNodi[nodo_id_]);
        st.nextToken(".");
        Integer num=new Integer(st.nextToken("."));
        return num.intValue();
    }
    
    private int getThirdLevelNetworkOfNode(int nodo_id_){
        StringTokenizer st=new StringTokenizer(this.nomiNodi[nodo_id_]);
        st.nextToken(".");
        st.nextToken(".");
        Integer num=new Integer(st.nextToken("."));
        return num.intValue();
    }
    
    public int[][] getLevel_3_Matrix(){
        if(this.getNumOfLevel()>2){
            Vector vett=new Vector();
            for(int i=0;i<this.numOfNode;i++ ){
                StringTokenizer st=new StringTokenizer(this.nomiNodi[i]);
                String nome=new String();
                nome=st.nextToken(".")+"."+st.nextToken(".")+"."+st.nextToken(".");
                if (!vett.contains(nome)){
                    vett.add(nome);
                }
            }
            int reti=vett.size();
            int[][] matrix=new int[reti][reti];
            for(int i=0;i<reti;i++){
                for(int j=0;j<reti;j++){
                    matrix[i][j]=0;
                }
            }
            for (int i=0;i<this.numOfArch;i++){
                StringTokenizer st=new StringTokenizer(this.nomiNodi[this.archi[i][0]]);
                String nodo_source=st.nextToken(".")+"."+st.nextToken(".")+"."+st.nextToken(".");
                st=new StringTokenizer(this.nomiNodi[this.archi[i][1]]);
                String nodo_dest=st.nextToken(".")+"."+st.nextToken(".")+"."+st.nextToken(".");
                matrix[vett.indexOf(nodo_source)][vett.indexOf(nodo_dest)]++;
            }
            for(int i=0;i<reti;i++){
                matrix[i][i]=0;
            }
            return matrix;
        }
        else{
            return null;
        }
    }
    
    public String[] getLevel_3_Name(){
        Vector vett=new Vector();
        for(int i=0;i<this.numOfNode;i++ ){
            StringTokenizer st=new StringTokenizer(this.nomiNodi[i]);
            String nome=new String();
            nome=st.nextToken(".")+"."+st.nextToken(".")+"."+st.nextToken(".");
            if (!vett.contains(nome)){
                vett.add(nome);
            }
        }
        String[] nomi=new String[vett.size()];
        for(int i=0;i<vett.size();i++){
            nomi[i]=(String)(vett.elementAt(i));
        }
        return nomi;
    }
    
    public String[] getLevel_1_Name(){
        Vector vett=new Vector();
        for(int i=0;i<this.numOfNode;i++ ){
            StringTokenizer st=new StringTokenizer(this.nomiNodi[i]);
            String nome=new String();
            nome=st.nextToken(".");
            if (!vett.contains(nome)){
                vett.add(nome);
            }
        }
        String[] nomi=new String[vett.size()];
        for(int i=0;i<vett.size();i++){
            nomi[i]=(String)(vett.elementAt(i));
        }
        return nomi;
    }
    
    public String[] getLevel_2_Name(){
        Vector vett=new Vector();
        for(int i=0;i<this.numOfNode;i++ ){
            StringTokenizer st=new StringTokenizer(this.nomiNodi[i]);
            String nome=new String();
            nome=st.nextToken(".")+"."+st.nextToken(".");
            if (!vett.contains(nome)){
                vett.add(nome);
            }
        }
        String[] nomi=new String[vett.size()];
        for(int i=0;i<vett.size();i++){
            nomi[i]=(String)(vett.elementAt(i));
        }
        return nomi;
    }
    
    
    /** restituisce i nomi dei nodi della rete di terzo livello
     indicata dal parametro rete Es rete=1.2 */
    public String[] getLevel_3_NameOfNet(String rete){
        if(this.getNumOfLevel()>2){
            rete=rete+".";
           Vector vett=new Vector();
           //genero il vettore con i nomi
           for(int i=0;i<this.numOfNode;i++){
               String nodo_corrente=new String(this.nomiNodi[i]);
               if (nodo_corrente.startsWith(rete)){
                   StringTokenizer st=new StringTokenizer(this.nomiNodi[i]);
                   String nome=new String();
                   nome=st.nextToken(".")+"."+st.nextToken(".")+"."+st.nextToken(".");
                   if (!vett.contains(nome)){
                       vett.add(nome);
                   }
               }
           }
           String[] nomi=new String[vett.size()];
           for (int i=0;i<vett.size();i++){
               nomi[i]=(String)(vett.elementAt(i));
           }
           return nomi;
        }
        else{
            return null;
        }
    }
    
    
    /** restituisce i nomi dei nodi della rete di secondo livello
     indicata dal parametro rete Es rete=4*/
    public String[] getLevel_2_NameOfNet(String rete){
        if(this.getNumOfLevel()>1){
            rete=rete+".";
           Vector vett=new Vector();
           //genero il vettore con i nomi
           for(int i=0;i<this.numOfNode;i++){
               String nodo_corrente=new String(this.nomiNodi[i]);
               if (nodo_corrente.startsWith(rete)){
                   StringTokenizer st=new StringTokenizer(this.nomiNodi[i]);
                   String nome=new String();
                   nome=st.nextToken(".")+"."+st.nextToken(".");
                   if (!vett.contains(nome)){
                       vett.add(nome);
                   }
               }
           }
           String[] nomi=new String[vett.size()];
           for (int i=0;i<vett.size();i++){
               nomi[i]=(String)(vett.elementAt(i));
           }
           return nomi;
        }
        else{
            return null;
        }
    }
    
    /** Restituisce la matrice relativa alla rete di secondo livello
     indicata dalla variabile rete Es rete=8 */
    public int[][] getLevel_2_MatrixOfNet(String rete){
        if(this.getNumOfLevel()>1){
            rete=rete+".";
           Vector vett=new Vector();
           //genero il vettore con i nomi
           for(int i=0;i<this.numOfNode;i++){
               String nodo_corrente=new String(this.nomiNodi[i]);
               if (nodo_corrente.startsWith(rete)){
                   StringTokenizer st=new StringTokenizer(this.nomiNodi[i]);
                   String nome=new String();
                   nome=st.nextToken(".")+"."+st.nextToken(".");
                   if (!vett.contains(nome)){
                       vett.add(nome);
                   }
               }
           }
           //genero matrice vuota
           int reti=vett.size();
            int[][] matrix=new int[reti][reti];
            for(int i=0;i<reti;i++){
                for(int j=0;j<reti;j++){
                    matrix[i][j]=0;
                }
            }
            // riempio la matrice
            for (int i=0;i<this.numOfArch;i++){
                String nodo1=new String(this.nomiNodi[this.archi[i][0]]);
                String nodo2=new String(this.nomiNodi[this.archi[i][1]]);
                if(nodo1.startsWith(rete)&& nodo2.startsWith(rete)){
                    StringTokenizer st=new StringTokenizer(this.nomiNodi[this.archi[i][0]]);
                    String nodo_source=st.nextToken(".")+"."+st.nextToken(".");
                    st=new StringTokenizer(this.nomiNodi[this.archi[i][1]]);
                    String nodo_dest=st.nextToken(".")+"."+st.nextToken(".");
                    matrix[vett.indexOf(nodo_source)][vett.indexOf(nodo_dest)]++;
                }
            }
            //Azzero diagonale principale
            for(int i=0;i<reti;i++){
                matrix[i][i]=0;
            }
            return matrix;
        }
        else{
            return null;
        }
    }
    
    /** Restituisce la matrice relativa alla rete di terzo livello
     indicata dalla variabile rete Es rete=1.2 */
    public int[][] getLevel_3_MatrixOfNet(String rete){
        if(this.getNumOfLevel()>2){
            rete=rete+".";
           Vector vett=new Vector();
           //genero il vettore con i nomi
           for(int i=0;i<this.numOfNode;i++){
               String nodo_corrente=new String(this.nomiNodi[i]);
               if (nodo_corrente.startsWith(rete)){
                   StringTokenizer st=new StringTokenizer(this.nomiNodi[i]);
                   String nome=new String();
                   nome=st.nextToken(".")+"."+st.nextToken(".")+"."+st.nextToken(".");
                   if (!vett.contains(nome)){
                       vett.add(nome);
                   }
               }
           }
           //genero matrice vuota
           int reti=vett.size();
            int[][] matrix=new int[reti][reti];
            for(int i=0;i<reti;i++){
                for(int j=0;j<reti;j++){
                    matrix[i][j]=0;
                }
            }
            // riempio la matrice
            for (int i=0;i<this.numOfArch;i++){
                String nodo1=new String(this.nomiNodi[this.archi[i][0]]);
                String nodo2=new String(this.nomiNodi[this.archi[i][1]]);
                if(nodo1.startsWith(rete)&& nodo2.startsWith(rete)){
                    StringTokenizer st=new StringTokenizer(this.nomiNodi[this.archi[i][0]]);
                    String nodo_source=st.nextToken(".")+"."+st.nextToken(".")+"."+st.nextToken(".");
                    st=new StringTokenizer(this.nomiNodi[this.archi[i][1]]);
                    String nodo_dest=st.nextToken(".")+"."+st.nextToken(".")+"."+st.nextToken(".");
                    matrix[vett.indexOf(nodo_source)][vett.indexOf(nodo_dest)]++;
                }
            }
            //Azzero diagonale principale
            for(int i=0;i<reti;i++){
                matrix[i][i]=0;
            }
            return matrix;
        }
        else{
            return null;
        }
    }
    
    public int[][] getLevel_2_Matrix(){ 
        if(this.getNumOfLevel()>1){
            Vector vett=new Vector();
            for(int i=0;i<this.numOfNode;i++ ){
                StringTokenizer st=new StringTokenizer(this.nomiNodi[i]);
                String nome=new String();
                nome=st.nextToken(".")+"."+st.nextToken(".");
                if (!vett.contains(nome)){
                    vett.add(nome);
                }
            }
            int reti=vett.size();
            int[][] matrix=new int[reti][reti];
            for(int i=0;i<reti;i++){
                for(int j=0;j<reti;j++){
                    matrix[i][j]=0;
                }
            }
            for (int i=0;i<this.numOfArch;i++){
                StringTokenizer st=new StringTokenizer(this.nomiNodi[this.archi[i][0]]);
                String nodo_source=st.nextToken(".")+"."+st.nextToken(".");
                st=new StringTokenizer(this.nomiNodi[this.archi[i][1]]);
                String nodo_dest=st.nextToken(".")+"."+st.nextToken(".");
                matrix[vett.indexOf(nodo_source)][vett.indexOf(nodo_dest)]++;
            }
            for(int i=0;i<reti;i++){
                matrix[i][i]=0;
            }
            return matrix;
        }
        else{
            return null;
        }
    }
    
    public int[][] getLevel_1_Matrix(){
        int reti=this.getNumOfFirstLevelNetwork();
        int[][] matrix=new int[reti][reti];
        for(int i=0;i<reti;i++){
            for(int j=0;j<reti;j++){
                matrix[i][j]=0;
            }
        }
        for(int i=0;i<this.numOfArch;i++){
            int nodo_source=this.archi[i][0];
            int nodo_dest=this.archi[i][1];
            int source_net=this.getFirstLevelNetworkOfNode(nodo_source);
            int dest_net=this.getFirstLevelNetworkOfNode(nodo_dest);
            matrix[source_net][dest_net]++;
        }
        for(int i=0;i<reti;i++){
            matrix[i][i]=0;
        }
        return matrix;        
    }
    
    public String getInfo(){
        String stringa=new String();
        if(this.getNumOfLevel()==2){
            stringa="<HTML>Hierarchical network<BR>";
            stringa=stringa+"Numbers of nodes "+this.numOfNode+"<BR>";
            stringa=stringa+"Numbers of links "+this.numOfArch+"<BR>";
            stringa=stringa+"Grid size "+this.scale+" x "+this.scale+"<BR>";
            stringa=stringa+"Number of layers of networks "+this.getNumOfLevel()+"<BR>";
            stringa=stringa+"Number of networks of first level 1<BR>";
            stringa=stringa+"Number of networks of second level "+this.getNumOfFirstLevelNetwork()+"<BR>";
            stringa=stringa+"</HTML>";
        }
        if(this.getNumOfLevel()==3){
            stringa="<HTML>Hierarchical network<BR>";
            stringa=stringa+"Numbers of nodes "+this.numOfNode+"<BR>";
            stringa=stringa+"Numbers of links "+this.numOfArch+"<BR>";
            stringa=stringa+"Grid size "+this.scale+" x "+this.scale+"<BR>";
            stringa=stringa+"Number of layers of networks "+this.getNumOfLevel()+"<BR>";
            stringa=stringa+"Numero di reti di primo livelo livello 1<BR>";
            stringa=stringa+"Number of networks of second level "+this.getNumOfFirstLevelNetwork()+"<BR>";
            stringa=stringa+"Number of networks of third level "+this.getNumOfSecondLevelNetwork()+"<BR>";
            stringa=stringa+"</HTML>";
        }
        return stringa;
    }
    
}//fine classe
